package services.mes

import models.mes.{MesOrdersRepository, MesStockOrdersRec}
import play.api.Logging
import play.api.libs.json.{JsArray, JsValue, Json}
import services.kingdee.KingdeePostV2

import java.sql.Timestamp
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import javax.inject.Inject
import scala.collection.mutable
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext, Future}

class MoreMesStock @Inject()(
                              moreMesPost: MoreMesPost,
                              mesRepo: MesOrdersRepository,
                              kingdeePost: KingdeePostV2
                            )(implicit exec: ExecutionContext)
  extends Logging {

  private var mesPost = moreMesPost.setConfig("")
  private var kdPost = kingdeePost.setKdAppConfig(mesPost.kdAppConfig.dCID)
  private var stepTime = 1 // 1 Days

  def setStepTime(t: String) = {
    val time_str = "[DdHhMmSs]".r.findFirstIn(t).getOrElse("D").toUpperCase
    val time_num = "\\d+".r.findAllIn(t).mkString.toInt
    this.stepTime = time_str match {
      case "H" => if (time_num % 24 > 0) time_num / 24 + 1 else time_num / 24
      case "M" => if (time_num % 1440 > 0) time_num / 1440 + 1 else time_num / 1440
      case "S" => if (time_num % 86400 > 0) time_num / 86400 + 1 else time_num / 86400
      case _ => time_num
    }
    this
  }

  def setConfig(config: String) = {
    this.mesPost = moreMesPost.setConfig(config)
    this.kdPost = kingdeePost.setKdAppConfig(mesPost.kdAppConfig.dCID)
    this
  }

  private def getType(ts: String) = {
    val otype = List(
      ("CGRK", "STK_InStock"), //  # 采购入库
      ("CGTL", "PUR_MRB"), //  采购退料
      ("XSCK", "SAL_OUTSTOCK"), //  销售出库
      ("XSTH", "SAL_RETURNSTOCK"), //  销售退货
      ("FBDR", "STK_TRANSFERIN"), //  分步式调入
      ("FBDC", "STK_TRANSFEROUT"), //  分步式调出
      //      ("QTRK", "STK_MISCELLANEOUS"), // # 其他入库
      //      ("QTCK", "STK_MisDelivery"), //  其他出库
      ("STRK", "STK_OEMInStock"), // 受托材料入库
      ("STTL", "STK_OEMInStockRETURN"), //  受托材料退料
    )
    val result = if (ts.length <= 5) {
      otype.filter(_._1 == ts).map(_._2)
    } else {
      otype.filter(_._2 == ts).map(_._1)
    }
    if (result.isEmpty) "****" else result.head
  }

  private def getStockInOutOrder(otype: String, date: String = "") = {
    val formid = getType(otype)
    val stockId = formid match {
      case "STK_TRANSFERIN" => "FDestStockID"
      case "STK_TRANSFEROUT" => "FSrcStockID"
      case _ => "FStockID"
    }
    val qs = if (date == "") {
      val d = LocalDate.now()
        .minusDays(stepTime)
        .format(
          DateTimeFormatter
            .ofPattern("yyyyMMdd")
        )
      s"FModifyDate >= to_date('$d','yyyymmdd') " +
        s" and ${stockId}.FDeptId = 'MES系统' " +
        " and F_SEND_STATUS <> 'Y'"
    }
    else if (date.length == 8) {
      s"FModifyDate >= to_date('$date','yyyymmdd')" +
        s" and ${stockId}.FDeptId = 'MES系统'" +
        s" and F_SEND_STATUS <> 'Y'"
    }
    else {
      s"FBillNo = '$date'"
    }

    logger.debug(s"getStockInOutOrder FilterString: $qs")
    val lst: mutable.ArrayBuffer[MesStockOrdersRec] = mutable.ArrayBuffer()
    var startRow = 0
    val limit = 10
    var isEnd = true
    while (isEnd) {
      val para = Json.obj(
        "FormId" -> formid,
        "FieldKeys" -> "FBillNo,FDate,FModifyDate,FApproveDate,FDocumentStatus,FID,F_SEND_STATUS",
        // "FBillNo,FRowId,FMaterialId.fnumber,FDate,FModifyDate,FApproveDate,FStatus,FDocumentStatus,F_SEND_STATUS",
        "FilterString" -> qs,
        "OrderString" -> "",
        "TopRowCount" -> 0,
        "StartRow" -> lst.size,
        "Limit" -> limit
      )
      val res = Await.result(kdPost.executeBillQuery(para), Duration.Inf)
      logger.debug(s"${res.getClass}\tgetStockInOutOrder list: ${res}")
      val arr = Json.parse(res).as[Array[JsArray]]
      //        .map(f => f.value(0).as[String])
      isEnd = arr.length == limit
      arr.foreach(stockorder => {
        //"FBillNo,FDate,FModifyDate,FApproveDate,FDocumentStatus,FID,F_SEND_STATUS"
        val code = stockorder.value(0).as[String]
        val date = Timestamp.valueOf(
          stockorder.value(1).as[String].replace('T', ' ')
        )
        val modify = Timestamp.valueOf(
          stockorder.value(2).as[String].replace('T', ' ')
        )
        val approve = stockorder.value(3).asOpt[String]
        val status = stockorder.value(4).as[String]
        val fid = stockorder.value(5).as[Int]
        lst.append(
          MesStockOrdersRec(
            code = code,
            otype = otype,
            date = date,
            modify = modify,
            approve = {
              if (approve.isEmpty) None
              else Option(Timestamp.valueOf(
                approve.get.replace('T', ' ')
              ))
            },
            status = status,
            send = 0,
            result = "",
            fid = fid
          )
        )
      }
      )
    }
    //    lst.foreach(f => getStkOrderView(formid, f.value(0).as[String]))
    lst
  }


  private def getStkOrderView(formid: String, code: String = "") = {
    val response = kdPost.view(
      formid, Json.obj {
        "Number" -> code
      })
    response.flatMap {
      res => {
        logger.debug(s"getStkOrderView($code):${res.take(200)}^^^^^^")
        val js = Json.parse(res)
        if ((js \ "Result" \ "ResponseStatus" \ "IsSuccess").as[Boolean]) {
          //          println("YYYYYYYYY")
          sendStockInfo((js \ "Result" \ "Result").as[JsValue])
        } else {
          println("XXXXX")
          Future("Json.obj()")
        }
      }
    }

  }

  /**
   * 采购入库单
   *
   * @param Result
   * @return
   */
  private def changeCGRKInfo(Result: JsValue) = {
    logger.debug("changeCGRKInfo:")
    val Entry = Result("InStockEntry").as[JsArray].value
    val DOC_NO = Result("BillNo").as[String]
    val DOC_TYPE = "STK_InStock"
    //    val SUPPLIER_CODE = Result("SupplierId")("Number")
    //    val CUST_CODE = ""
    val PLAN_RECEIVE_DATE = Result("Date").as[String].replace('T', ' ') //  re.sub("T", " ", Result("Date"))
    val CREATE_TIME = Result("CreateDate").as[String].replace('T', ' ')
    val MEMO = "" // Result["NOTE"]
    val Fid = Result("Id").as[Int]
    val ITEM_LIST = Entry.map {
      v =>
        try {
          Json.obj(
            "ITEM_SEQ" -> v("Seq").as[Int], //# "1",
            "ITEM_CODE" -> v("MaterialId")("Number").as[String], //# "1001-00001",
            "PLAN_QTY" -> v("MustQty").as[Double], //# "100",
            "UNIT" -> v("UnitID")("Number").as[String], //# UnitId "QK",
            "IS_GIFT" -> "N",
            //# "CONNECT_SEQ": "",
            //# "CONNECT_DOC": "",
            "WH_CODE" -> v("StockId")("Number").as[String], //# "1001",
            "MEMO" -> v("Note").as[String], //#/ Description"备注信息"
            "Sid" -> v("Id").as[Int]
          )
        } catch {
          case e: Exception => {
            logger.debug("Entry.map:" + v.toString(), e);
            Json.obj()
          }
        }

    }
    //    logger.debug(ITEM_LIST.mkString)
    val h = Json.obj("DATA_AUTH" -> "1",
      "DOC_NO" -> DOC_NO,
      "DOC_TYPE" -> DOC_TYPE,
      //# "SUPPLIER_CODE": SUPPLIER_CODE,
      //# "CUST_CODE": CUST_CODE,
      "PLAN_RECEIVE_DATE" -> PLAN_RECEIVE_DATE,
      "CREATE_TIME" -> CREATE_TIME,
      "MEMO" -> MEMO,
      "ITEM_LIST" -> ITEM_LIST.toSeq,
      "Fid" -> Fid)
    Json.obj("dataList" -> h)
  }

  /**
   * 采购退料单
   *
   * @param Result
   * @return
   */
  private def changeCGTLInfo(Result: JsValue) = {
    logger.debug("changeCGTLInfo:")
    val Entry = Result("PUR_MRBENTRY").as[JsArray].value
    val DOC_NO = Result("BillNo").as[String]
    val DOC_TYPE = "PUR_MRB"
    //    val SUPPLIER_CODE = Result("SupplierId")("Number")
    //    val CUST_CODE = ""
    val PLAN_RECEIVE_DATE = Result("Date").as[String].replace('T', ' ') //  re.sub("T", " ", Result("Date"))
    val CREATE_TIME = Result("CreateDate").as[String].replace('T', ' ')
    val MEMO = Result("DESCRIPTION").as[String]
    val Fid = Result("Id").as[Int]
    val ITEM_LIST = Entry.map {
      v =>
        try {
          Json.obj(
            "ITEM_SEQ" -> v("Seq").as[Int], //# "1",
            "ITEM_CODE" -> v("MATERIALID")("Number").as[String], //# "1001-00001",
            "PLAN_QTY" -> v("RMREALQTY").as[Double], //# "100",
            "UNIT" -> v("FUnitID")("Number").as[String], //# UnitId "QK",
            "IS_GIFT" -> "N",
            //# "CONNECT_SEQ": "",
            //# "CONNECT_DOC": "",
            "WH_CODE" -> v("STOCKID")("Number").as[String], //# "1001",
            "MEMO" -> v("NOTE").as[String], //#/ Description"备注信息"
            "DOC_INPUT_NO" -> v("SRCBillNo").as[String],
            "Sid" -> v("Id").as[Int]
          )
        } catch {
          case e: Exception => {
            logger.debug("Entry.map:" + v.toString(), e);
            Json.obj()
          }
        }

    }
    //    logger.debug(ITEM_LIST.mkString)
    val h = Json.obj("DATA_AUTH" -> "1",
      "DOC_NO" -> DOC_NO,
      "DOC_TYPE" -> DOC_TYPE,
      //# "SUPPLIER_CODE": SUPPLIER_CODE,
      //# "CUST_CODE": CUST_CODE,
      "PLAN_OUTSTOCK_DATE" -> PLAN_RECEIVE_DATE,
      "CREATE_TIME" -> CREATE_TIME,
      "MEMO" -> MEMO,
      "ITEM_LIST" -> ITEM_LIST.toSeq,
      "Fid" -> Fid)
    Json.obj("dataList" -> h)
  }

  /**
   * 销售出库单
   *
   * @param Result
   * @return
   */
  private def changeXSCKInfo(Result: JsValue) = {
    logger.debug("changeXSCKInfo:")
    val Entry = Result("SAL_OUTSTOCKENTRY").as[JsArray].value
    val DOC_NO = Result("BillNo").as[String]
    val DOC_TYPE = "SAL_OUTSTOCK"
    //    val SUPPLIER_CODE = Result("SupplierId")("Number")
    //    val CUST_CODE = ""
    val PLAN_RECEIVE_DATE = Result("Date").as[String].replace('T', ' ') //  re.sub("T", " ", Result("Date"))
    val CREATE_TIME = Result("FCreateDate").as[String].replace('T', ' ')
    val MEMO = Result("Note").as[String]
    val Fid = Result("Id").as[Int]
    val ITEM_LIST = Entry.map {
      v =>
        try {
          Json.obj(
            "ITEM_SEQ" -> v("Seq").as[Int], //# "1",
            "ITEM_CODE" -> v("MaterialID")("Number").as[String], //# "1001-00001",
            "PLAN_QTY" -> v("MustQty").as[Double], //# "100",
            "UNIT" -> v("UnitID")("Number").as[String], //# UnitId "QK",
            "IS_GIFT" -> "N",
            //# "CONNECT_SEQ": "",
            //# "CONNECT_DOC": "",
            "WH_CODE" -> v("StockID")("Number").as[String], //# "1001",
            "MEMO" -> v("Note").as[String], //#/ Description"备注信息"
            "Sid" -> v("Id").as[Int]
          )
        } catch {
          case e: Exception => {
            logger.debug("Entry.map:" + v.toString(), e);
            Json.obj()
          }
        }

    }
    //    logger.debug(ITEM_LIST.mkString)
    val h = Json.obj("DATA_AUTH" -> "1",
      "DOC_NO" -> DOC_NO,
      "DOC_TYPE" -> DOC_TYPE,
      //# "SUPPLIER_CODE": SUPPLIER_CODE,
      //# "CUST_CODE": CUST_CODE,
      "PLAN_OUTSTOCK_DATE" -> PLAN_RECEIVE_DATE,
      "CREATE_TIME" -> CREATE_TIME,
      "MEMO" -> MEMO,
      "ITEM_LIST" -> ITEM_LIST.toSeq,
      "Fid" -> Fid)
    Json.obj("dataList" -> h)
  }

  /**
   * 销售退货单
   *
   * @param Result
   * @return
   */
  private def changeXSTHInfo(Result: JsValue) = {
    logger.debug("changeXSTHInfo:")
    val Entry = Result("SAL_RETURNSTOCKENTRY").as[JsArray].value
    val DOC_NO = Result("BillNo").as[String]
    val DOC_TYPE = "SAL_RETURNSTOCK"
    //    val SUPPLIER_CODE = Result("SupplierId")("Number")
    //    val CUST_CODE = ""
    val PLAN_RECEIVE_DATE = Result("Date").as[String].replace('T', ' ') //  re.sub("T", " ", Result("Date"))
    val CREATE_TIME = Result("CreateDate").as[String].replace('T', ' ')
    val MEMO = Result("FNote").as[String]
    val Fid = Result("Id").as[Int]
    val ITEM_LIST = Entry.map {
      v =>
        try {
          Json.obj(
            "ITEM_SEQ" -> v("Seq").as[Int], //# "1",
            "ITEM_CODE" -> v("MaterialId")("Number").as[String], //# "1001-00001",
            "PLAN_QTY" -> v("Mustqty").as[Double], //# "100",
            "UNIT" -> v("UnitId")("Number").as[String], //# UnitId "QK",
            "IS_GIFT" -> "N",
            //# "CONNECT_SEQ": "",
            //# "CONNECT_DOC": "",
            "WH_CODE" -> v("StockId")("Number").as[String], //# "1001",
            "MEMO" -> v("Note").as[String], //#/ Description"备注信息"
            "CONNECT_DOC" -> v("SrcBillNo").as[String],
            "Sid" -> v("Id").as[Int]
          )
        } catch {
          case e: Exception => {
            logger.debug("Entry.map:" + v.toString(), e);
            Json.obj()
          }
        }

    }
    //    logger.debug(ITEM_LIST.mkString)
    val h = Json.obj("DATA_AUTH" -> "1",
      "DOC_NO" -> DOC_NO,
      "DOC_TYPE" -> DOC_TYPE,
      //# "SUPPLIER_CODE": SUPPLIER_CODE,
      //# "CUST_CODE": CUST_CODE,
      "PLAN_RECEIVE_DATE" -> PLAN_RECEIVE_DATE,
      "CREATE_TIME" -> CREATE_TIME,
      "MEMO" -> MEMO,
      "ITEM_LIST" -> ITEM_LIST.toSeq,
      "Fid" -> Fid)
    Json.obj("dataList" -> h)
  }

  private def changeQTRKInfo(purInfo: JsValue) = {
    Json.obj()
  }

  private def changeQTCKInfo(purInfo: JsValue) = {
    Json.obj()
  }

  /**
   * 分步式调入单
   *
   * @param Result
   * @return
   */
  private def changeFBDRInfo(Result: JsValue) = {
    logger.debug("changeFBDRInfo:")
    val Entry = Result("STK_STKTRANSFERINENTRY").as[JsArray].value
    val DOC_NO = Result("BillNo").as[String]
    val DOC_TYPE = "STK_TRANSFERIN"
    //    val SUPPLIER_CODE = Result("SupplierId")("Number")
    //    val CUST_CODE = ""
    val PLAN_RECEIVE_DATE = Result("Date").as[String].replace('T', ' ') //  re.sub("T", " ", Result("Date"))
    val CREATE_TIME = Result("CreateDate").as[String].replace('T', ' ')
    val MEMO = Result("NOTE").as[String]
    val Fid = Result("Id").as[Int]
    val ITEM_LIST = Entry.map {
      v =>
        try {
          Json.obj(
            "ITEM_SEQ" -> v("Seq").as[Int], //# "1",
            "ITEM_CODE" -> v("MaterialID")("Number").as[String], //# "1001-00001",
            "PLAN_QTY" -> v("FQty").as[Double], //# "100",
            "UNIT" -> v("UnitID")("Number").as[String], //# UnitId "QK",
            "IS_GIFT" -> "N",
            //# "CONNECT_SEQ": "",
            //# "CONNECT_DOC": "",
            "WH_CODE" -> v("DestStockID")("Number").as[String], //# "1001",
            "MEMO" -> v("EntryNote").as[String], //#/ Description"备注信息"
            "Sid" -> v("Id").as[Int]
          )
        } catch {
          case e: Exception => {
            logger.debug("Entry.map:" + v.toString(), e)
            Json.obj()
          }
        }

    }
    //    logger.debug(ITEM_LIST.mkString)
    val h = Json.obj("DATA_AUTH" -> "1",
      "DOC_NO" -> DOC_NO,
      "DOC_TYPE" -> DOC_TYPE,
      //# "SUPPLIER_CODE": SUPPLIER_CODE,
      //# "CUST_CODE": CUST_CODE,
      "PLAN_RECEIVE_DATE" -> PLAN_RECEIVE_DATE,
      "CREATE_TIME" -> CREATE_TIME,
      "MEMO" -> MEMO,
      "ITEM_LIST" -> ITEM_LIST.toSeq,
      "Fid" -> Fid)
    Json.obj("dataList" -> h)
  }

  /**
   * 分步式调出单
   *
   * @param Result
   * @return
   */
  private def changeFBDCInfo(Result: JsValue) = {
    logger.debug("changeFBDRInfo:")
    val Entry = Result("STK_STKTRANSFEROUTENTRY").as[JsArray].value
    val DOC_NO = Result("BillNo").as[String]
    val DOC_TYPE = "STK_TRANSFEROUT"
    //    val SUPPLIER_CODE = Result("SupplierId")("Number")
    //    val CUST_CODE = ""
    val PLAN_RECEIVE_DATE = Result("Date").as[String].replace('T', ' ') //  re.sub("T", " ", Result("Date"))
    val CREATE_TIME = Result("CreateDate").as[String].replace('T', ' ')
    val MEMO = Result("NOTE").as[String]
    val Fid = Result("Id").as[Int]
    val ITEM_LIST = Entry.map {
      v =>
        try {
          Json.obj(
            "ITEM_SEQ" -> v("Seq").as[Int], //# "1",
            "ITEM_CODE" -> v("MaterialID")("Number").as[String], //# "1001-00001",
            "PLAN_QTY" -> v("FQty").as[Double], //# "100",
            "UNIT" -> v("UnitID")("Number").as[String], //# UnitId "QK",
            "IS_GIFT" -> "N",
            //# "CONNECT_SEQ": "",
            //# "CONNECT_DOC": "",
            "WH_CODE" -> v("SrcStockID")("Number").as[String], //# "1001",
            "MEMO" -> v("EntryNote").as[String], //#/ Description"备注信息"
            "Sid" -> v("Id").as[Int]
          )
        } catch {
          case e: Exception => {
            logger.debug("Entry.map:" + v.toString(), e);
            Json.obj()
          }
        }

    }
    //    logger.debug(ITEM_LIST.mkString)
    val h = Json.obj("DATA_AUTH" -> "1",
      "DOC_NO" -> DOC_NO,
      "DOC_TYPE" -> DOC_TYPE,
      //# "SUPPLIER_CODE": SUPPLIER_CODE,
      //# "CUST_CODE": CUST_CODE,
      "PLAN_OUTSTOCK_DATE" -> PLAN_RECEIVE_DATE,
      "CREATE_TIME" -> CREATE_TIME,
      "MEMO" -> MEMO,
      "ITEM_LIST" -> ITEM_LIST.toSeq,
      "Fid" -> Fid)
    Json.obj("dataList" -> h)
  }

  /**
   * 受托入库
   *
   * @param purInfo
   * @return
   */
  private def changeSTRKInfo(Result: JsValue) = {
    logger.debug("changeSTRKInfo:")
    val Entry = Result("OEMInStockEntry").as[JsArray].value
    val DOC_NO = Result("BillNo").as[String]
    val DOC_TYPE = "STK_OEMInStock"
    //    val SUPPLIER_CODE = Result("SupplierId")("Number")
    //    val CUST_CODE = ""
    val PLAN_RECEIVE_DATE = Result("Date").as[String].replace('T', ' ') //  re.sub("T", " ", Result("Date"))
    val CREATE_TIME = Result("CreateDate").as[String].replace('T', ' ')
    val MEMO = Result("Note").as[String]
    val Fid = Result("Id").as[Int]
    val ITEM_LIST = Entry.map {
      v =>
        try {
          Json.obj(
            "ITEM_SEQ" -> v("Seq").as[Int], //# "1",
            "ITEM_CODE" -> v("MaterialId")("Number").as[String], //# "1001-00001",
            "PLAN_QTY" -> v("Qty").as[Double], //# "100",
            "UNIT" -> v("UnitID")("Number").as[String], //# UnitId "QK",
            "IS_GIFT" -> "N",
            //# "CONNECT_SEQ": "",
            //# "CONNECT_DOC": "",
            "WH_CODE" -> v("StockId")("Number").as[String], //# "1001",
            "MEMO" -> v("Note").as[String], //#/ Description"备注信息"
            "Sid" -> v("Id").as[Int]
          )
        } catch {
          case e: Exception => {
            logger.debug("Entry.map:" + v.toString(), e);
            Json.obj()
          }
        }

    }
    //    logger.debug(ITEM_LIST.mkString)
    val h = Json.obj("DATA_AUTH" -> "1",
      "DOC_NO" -> DOC_NO,
      "DOC_TYPE" -> DOC_TYPE,
      //# "SUPPLIER_CODE": SUPPLIER_CODE,
      //# "CUST_CODE": CUST_CODE,
      "PLAN_RECEIVE_DATE" -> PLAN_RECEIVE_DATE,
      "CREATE_TIME" -> CREATE_TIME,
      "MEMO" -> MEMO,
      "ITEM_LIST" -> ITEM_LIST.toSeq,
      "Fid" -> Fid)
    Json.obj("dataList" -> h)
  }

  /**
   * 受托退料
   *
   * @param Result
   * @return
   */
  private def changeSTTLInfo(Result: JsValue) = {
    logger.debug("changeSTTLInfo:")
    val Entry = Result("OEMInStockRTNEntry").as[JsArray].value
    val DOC_NO = Result("BillNo").as[String]
    val DOC_TYPE = "STK_OEMInStockRETURN"
    //    val SUPPLIER_CODE = Result("SupplierId")("Number")
    //    val CUST_CODE = ""
    val PLAN_RECEIVE_DATE = Result("Date").as[String].replace('T', ' ') //  re.sub("T", " ", Result("Date"))
    val CREATE_TIME = Result("FCreateDate").as[String].replace('T', ' ')
    val MEMO = Result("Note").as[String]
    val Fid = Result("Id").as[Int]
    val ITEM_LIST = Entry.map {
      v =>
        try {
          Json.obj(
            "ITEM_SEQ" -> v("Seq").as[Int], //# "1",
            "ITEM_CODE" -> v("MaterialId")("Number").as[String], //# "1001-00001",
            "PLAN_QTY" -> v("Qty").as[Double], //# "100",
            "UNIT" -> v("UnitID")("Number").as[String], //# UnitId "QK",
            "IS_GIFT" -> "N",
            //# "CONNECT_SEQ": "",
            //# "CONNECT_DOC": "",
            "WH_CODE" -> v("StockId")("Number").as[String], //# "1001",
            "MEMO" -> v("Note").as[String], //#/ Description"备注信息"
            "Sid" -> v("Id").as[Int]
          )
        } catch {
          case e: Exception => {
            logger.debug("Entry.map:" + v.toString(), e);
            Json.obj()
          }
        }

    }
    //    logger.debug(ITEM_LIST.mkString)
    val h = Json.obj("DATA_AUTH" -> "1",
      "DOC_NO" -> DOC_NO,
      "DOC_TYPE" -> DOC_TYPE,
      //# "SUPPLIER_CODE": SUPPLIER_CODE,
      //# "CUST_CODE": CUST_CODE,
      "PLAN_OUTSTOCK_DATE" -> PLAN_RECEIVE_DATE,
      "CREATE_TIME" -> CREATE_TIME,
      "MEMO" -> MEMO,
      "ITEM_LIST" -> ITEM_LIST.toSeq,
      "Fid" -> Fid)
    Json.obj("dataList" -> h)
  }

  private def sendStockInfo(purInfo: JsValue) = {
    val code: String = purInfo("BillNo").as[String]
    val formid: String = purInfo("FFormId").as[String]
    val fid = purInfo("Id").as[Int]
    val ordertype = getType(formid)
    logger.debug(s"sendStockInfo($code, $ordertype, ${purInfo.toString().take(100)})")
    val data = ordertype match {
      case "CGRK" => changeCGRKInfo(purInfo)
      case "CGTL" => changeCGTLInfo(purInfo)
      case "XSCK" => changeXSCKInfo(purInfo)
      case "XSTH" => changeXSTHInfo(purInfo)
      //      case "QTRK" => changeQTRKInfo(purInfo)
      //      case "QTCK" => changeQTCKInfo(purInfo)
      case "FBDR" => changeFBDRInfo(purInfo)
      case "FBDC" => changeFBDCInfo(purInfo)
      case "STRK" => changeSTRKInfo(purInfo)
      case "STTL" => changeSTTLInfo(purInfo)
      case _ => {
        logger.debug(s"ordertype=$ordertype")
        Json.obj()
      }
    }
    logger.debug(data.toString)
    val mes_res = ordertype match {
      case "CGRK" | "XSTH" | "QTRK" | "FBDR" | "STRK" => {
        //        Future("{\"result\":true,\"msg\":\"更新成功\",\"content\":[\"\"]}")
        mesPost.saveStockIn(data)
      }
      case "CGTL" | "XSCK" | "QTCK" | "FBDC" | "STTL" => {
        //        Future("{\"result\":true,\"msg\":\"更新成功\",\"content\":[\"\"]}")
        mesPost.saveStockOut(data)
      }
      case _ => Future("单据类型不在范围内")
    }
    mes_res.flatMap {
      res => {
        val msg = s"mesPost.Stock($code): ${data.toString} => $res"
        logger.info(msg)
        val boolean = {
          val i = res.indexOf("result")
          if (i >= 0) res.substring(i, i + 14).indexOf("true") > 0
          else false
        }
        if (boolean) {
          mesRepo.stkSetSendSign(code, 1, res).flatMap {
            setSendSign => {
              kdPost.save(formid, s"""{"NeedUpDateFields":["F_SEND_STATUS"],"Model":{"FID":$fid,"F_SEND_STATUS":"Y"}}""")
                .map(
                  kdsend => {
                    logger.info(s"$code set F_SEND_STATUS=Y >$setSendSign $kdsend")
                    res
                  }
                )
            }
          }
        }
        else {
          mesRepo.stkSetSendSign(code, -1, res).map(setSendSign => {
            logger.info(s"$code set F_SEND_STATUS=Y >$setSendSign")
            res
          })
        }
      }
    }
  }

  private def sendStock2Mes(stockorder: MesStockOrdersRec) = {
    val ordertype = stockorder.otype
    val formid = getType(ordertype)
    kdPost.save(formid,
      s"""
         |{"NeedUpDateFields":["F_SEND_STATUS"],
         | "Model": {"FID": ${stockorder.fid}, "F_SEND_STATUS": "F"}
         |}""".stripMargin
    ).flatMap {
      save_res => {
        logger.debug(s"${stockorder.code} set F_SEND_STATUS=F >$save_res")
        val boolean = {
          val i = save_res.indexOf("IsSuccess")
          if (i >= 0) save_res.substring(i, i + 20).indexOf("true") > 0
          else false
        }
        if (boolean) {
          getStkOrderView(formid, code = stockorder.code)

        } else {
          Future(save_res)
        }
      }
    }
  }

  /**
   * @param ordertype in ["CGRK","XSTH","QTRK","CGTL","XSCK","QTCK","FBDR","FBDC","STRK","STTL"]
   * @param filterArg like "20220123" or Fbillno or ""
   */
  def putStockInOut2Mes(ordertype: String = "", filterArg: String = "") = {
    val formid = getType(ordertype)
    val stock_list = getStockInOutOrder(otype = ordertype, date = filterArg).toSet
    logger.debug(s"putStockInOut2Mes($ordertype,$filterArg):" + stock_list.toString)
    //    for (stockorder <- stock_list)
    val res = stock_list.map { stockorder =>
      logger.debug(s"StockInOut:${stockorder.toString}")
      val send_sign = mesRepo.stkUpInsert(stockorder)
      send_sign.flatMap {
        send =>
          logger.debug(s"putStockInOut2Mes send_sign is $send")
          if (send && filterArg.length <= 8) Future("")
          else sendStock2Mes(stockorder)
      }
    }
    if (res.nonEmpty) res.head else Future("")
  }

  def runTask() = {
    putStockInOut2Mes("CGRK")
    putStockInOut2Mes("CGTL")
    putStockInOut2Mes("XSCK")
    putStockInOut2Mes("XSTH")
    //    putStockInOut2Mes("QTRK")
    //    putStockInOut2Mes("QTCK")
    putStockInOut2Mes("FBDC")
    putStockInOut2Mes("FBDR")
    putStockInOut2Mes("STRK")
    putStockInOut2Mes("STTL")
  }

}
